﻿/* ==============================================================================
* 功能描述：Room
* 创 建 者：青金石
* 创建日期：2020/6/2 17:11:14
* ==============================================================================*/

using System.Collections.Generic;

public class Room
{
    public int id = 0;
    public int maxCount = 0;

    //房间内的玩家列表，string为玩家id，bool为在房间内
    public Dictionary<string, bool> playerIds = new Dictionary<string, bool>();

    //出生点（位置和旋转）
    public static float[,,] birthConfig = new float[2, 1, 6]{
    //阵营1
        {
            {0,0,-12,0,0,0}
        },
    //阵营2
        {
            {0,0,12,0,180,0}
        }
    };

    //房主id
    public string ownerId = "";

    //房间状态枚举
    public enum Status
    {
        PREPARING = 0,
        FIGHTING = 1
    }

    //房间状态
    public Status status = Status.PREPARING;

    //玩家加入房间
    public bool AddPlayer(string id)
    {
        Player player = PlayerManager.GetPlayer(id);
        if (player == null)
        {
            System.Console.WriteLine("玩家不存在，加入房间失败");
            return false;
        }
        //房间人数超过上限
        if (playerIds.Count >= maxCount)
        {
            System.Console.WriteLine("房间人数超过上限");
            return false;
        }
        //准备状态才能加入
        if (status != Status.PREPARING)
        {
            System.Console.WriteLine("准备状态才能加入");
            return false;
        }
        //玩家已经在房间内
        if (playerIds.ContainsKey(id))
        {
            System.Console.WriteLine("玩家已经在房间内");
            return false;
        }
        //加入列表
        playerIds.Add(id, true);
        //设置玩家数据
        player.camp = SwitchCamp();
        player.roomID = this.id;
        //分配房主，最先进房间的人是房主
        if (string.IsNullOrEmpty(ownerId))
        {
            ownerId = player.id;
        }
        //向房间内广播,所有房间内的玩家更新房间信息
        BroadCast(ToMsg());
        return true;
    }

    //玩家离开
    public bool RemovePlayer(string id)
    {
        Player player = PlayerManager.GetPlayer(id);
        if (player == null)
        {
            System.Console.WriteLine("room.RemovePlayer fail,player is null");
            return false;
        }
        if (!playerIds.ContainsKey(id))
        {
            System.Console.WriteLine("room.RemovePlayer fail,not in this room");
            return false;
        }
        playerIds.Remove(id);

        player.camp = 0;
        player.roomID = -1;
        //房主离开，重新分配房主
        if (IsOwner(player))
        {
            ownerId = SwitchOwner();
        }
        if (status == Status.FIGHTING)
        {
            player.data.escape++;
            MsgLeaveBattle msg = new MsgLeaveBattle();
            msg.id = id;
            BroadCast(msg);
        }
        //房间空了，删除房间
        if (playerIds.Count == 0)
        {
            RoomManager.RemoveRoom(this.id);
        }
        BroadCast(ToMsg());
        return true;
    }

    //分配阵营
    public int SwitchCamp()
    {
        int count1 = 0;
        int count2 = 0;
        //平均分配阵营
        foreach (string id in playerIds.Keys)
        {
            Player player = PlayerManager.GetPlayer(id);
            if (player.camp == 1) { count1++; }
            if (player.camp == 2) { count2++; }
        }
        if (count1 <= count2)
        {
            return 1;
        }
        else
        {
            return 2;
        }
    }

    //分配房主，第一个人当房主
    public string SwitchOwner()
    {
        foreach (string id in playerIds.Keys)
        {
            return id;
        }
        return "";
    }

    //向房间内广播

    public void BroadCast(MsgBase msgBase)
    {
        foreach (string id in playerIds.Keys)
        {
            Player player = PlayerManager.GetPlayer(id);
            player.Send(msgBase);
        }
    }

    //生成MsgGetRoomInfo协议
    public MsgBase ToMsg()
    {
        MsgGetRoomInfo msg = new MsgGetRoomInfo();
        int count = playerIds.Count;
        msg.infos = new PlayerInfo[count];
        int i = 0;
        foreach (string id in playerIds.Keys)
        {
            Player player = PlayerManager.GetPlayer(id);
            PlayerInfo info = new PlayerInfo();
            PlayerData data = player.data;
            info.win = data.win;
            info.lose = data.lose;
            info.escape = data.escape;
            info.camp = player.camp;
            info.isOwner = 0;
            info.name = data.name;
            if (IsOwner(player))
            {
                info.isOwner = 1;
            }
            msg.infos[i] = info;
            i++;
        }
        return msg;
    }

    public bool IsOwner(Player player)
    {
        return player.id == ownerId;
    }

    /// <summary>
    /// 是否能开启战斗
    /// </summary>
    /// <returns></returns>
    private bool CanStartBattle()
    {
        //房间处于准备状态才能开战
        if (status != Status.PREPARING)
        {
            return false;
        }
        int count1 = 0, count2 = 0;
        foreach (string id in playerIds.Keys)
        {
            Player player = PlayerManager.GetPlayer(id);
            if (player.camp == 1)
            {
                count1++;
            }
            else
            {
                count2++;
            }
        }
        //每个阵营至少有一人
        if (count1 < 1 || count2 < 1)
        {
            return false;
        }
        return true;
    }

    /// <summary>
    /// 设置出生点
    /// </summary>
    /// <param name="player"></param>
    /// <param name="index">出生点索引</param>
    private void SetBirthPos(Player player, int index)
    {
        int camp = player.camp;
        player.x = birthConfig[camp - 1, index, 0];
        player.y = birthConfig[camp - 1, index, 1];
        player.z = birthConfig[camp - 1, index, 2];
        player.ex = birthConfig[camp - 1, index, 3];
        player.ey = birthConfig[camp - 1, index, 4];
        player.ez = birthConfig[camp - 1, index, 5];
    }

    /// <summary>
    /// 重设房间内玩家，重置出生点和生命值
    /// </summary>
    private void ResetPlayers()
    {
        int count1 = 0, count2 = 0;
        foreach (string id in playerIds.Keys)
        {
            Player player = PlayerManager.GetPlayer(id);
            player.hp = 100;
            if (player.camp == 1)
            {
                SetBirthPos(player, count1);
                count1++;
            }
            else
            {
                SetBirthPos(player, count2);
                count2++;
            }
        }
    }

    /// <summary>
    /// 将玩家信息转换为HeroInfo
    /// </summary>
    /// <param name="player"></param>
    /// <returns></returns>
    private HeroInfo PlayerToHeroInfo(Player player)
    {
        HeroInfo heroInfo = new HeroInfo();
        heroInfo.x = player.x;
        heroInfo.y = player.y;
        heroInfo.z = player.z;
        heroInfo.ex = player.ex;
        heroInfo.ey = player.ey;
        heroInfo.ez = player.ez;
        heroInfo.id = player.id;
        heroInfo.hp = player.hp;
        heroInfo.camp = player.camp;
        heroInfo.name = player.data.name;
        return heroInfo;
    }

    /// <summary>
    /// 开始战斗
    /// </summary>
    /// <returns></returns>
    public bool StartBattle()
    {
        if (!CanStartBattle())
        {
            return false;
        }
        status = Status.FIGHTING;
        ResetPlayers();
        MsgEnterBattle msg = new MsgEnterBattle();
        msg.heroInfos = new HeroInfo[playerIds.Count];
        msg.mapID = 1;
        int count = 0;
        foreach (string id in playerIds.Keys)
        {
            Player player = PlayerManager.GetPlayer(id);

            msg.heroInfos[count] = PlayerToHeroInfo(player);
            count++;
        }
        BroadCast(msg);
        return true;
    }

    /// <summary>
    /// 玩家存活状态
    /// </summary>
    /// <param name="player"></param>
    /// <returns></returns>
    public bool isDie(Player player)
    {
        return player.hp <= 0;
    }

    /// <summary>
    /// 判断胜负
    /// </summary>
    /// <returns></returns>
    public int Judgement()
    {
        int winCamp = 0;
        int count1 = 0, count2 = 0;
        foreach (string id in playerIds.Keys)
        {
            Player player = PlayerManager.GetPlayer(id);
            if (!isDie(player))
            {
                if (player.camp == 1)
                {
                    count1++;
                }
                else
                {
                    count2++;
                }
            }
        }
        if (count1 <= 0)
        {
            winCamp = 2;
        }
        else if (count2 <= 0)
        {
            winCamp = 1;
        }
        return winCamp;
    }

    private long lastJudageTime = 0;//上一次检测时间
    private float judgeInterval = 5f;//判断胜负间隔

    /// <summary>
    /// 定时判断胜负
    /// </summary>
    public void Update()
    {
        if (status != Status.FIGHTING)
        {
            return;
        }
        if (NetManager.GetTimeStamp() - lastJudageTime < judgeInterval)
        {
            return;
        }
        lastJudageTime = NetManager.GetTimeStamp();
        int winCamp = Judgement();
        //未分出胜负
        if (winCamp == 0)
        {
            return;
        }
        status = Status.PREPARING;
        foreach (string id in playerIds.Keys)
        {
            Player player = PlayerManager.GetPlayer(id);
            if (player.camp == winCamp)
            {
                player.data.win++;
            }
            else
            {
                player.data.lose++;
            }
        }
        MsgBattleResult msg = new MsgBattleResult();
        msg.winCamp = winCamp;
        BroadCast(msg);
    }
}